(function() {
	var inherits = require('util').inherits;
	var EventEmitter = require('events').EventEmitter;

	var obj_has = require("../_include/obj_con").has;
	//数据缓存文件
	var _db = require("./.db/data.cache.json");
	//索引缓存文件
	var _index;

	var _ti;
	var fs = require("fs");

	setInterval(function() {
		foo.__updateCache("data.cache." + (new Date).format("yy-MM-dd[HH=mm=ss]") + ".json");
		var r = /data\.cache\.(\d\d)\-(\d\d)\-(\d\d)\[(\d\d)\=(\d\d)\=(\d\d)\]\.json/;
		var timeline = 3 * 24 * 60 * 60 * 1000; //3天72小时
		fs.readdirSync(__dirname + "/.db/").forEach(function(fileName) {
			var match_info = fileName.match(r);
			if (match_info) {
				var date = new Date("20" + match_info.slice(1, 4).join("/") + " " + match_info.slice(4).join(":"));
				if ((+new Date() - timeline) > +date) { //如果这个文件的存在时间超过3天，删除
					fs.unlinkSync(__dirname + "/.db/" + fileName);
				}
			}
		});
	}, 3 * 60 * 60 * 1000); //3小时进行一次数据备份，删除3天前的数据

	process.on('uncaughtException', function(err) {
		console.info("进程未知错误，强行数据写入", err, err.stack);
		foo.__updateCache();
	});

	function _on_db_exit(type) {
		return function() {
			console.info("进程意外中断，强行数据写入", type);
			foo.__updateCache();
			process.exit();
		}
	};
	process.on('SIGHUP', _on_db_exit("SIGHUP"));
	process.on('SIGINT', _on_db_exit("SIGINT"));
	process.on('SIGQUIT', _on_db_exit("SIGQUIT"));
	process.on('SIGABRT', _on_db_exit("SIGABRT"));
	process.on('SIGTERM', _on_db_exit("SIGTERM"));
	var foo = {
		__updateCache: function(fileName) {
			console.time("parse_data");
			var _data = JSON._stringify(_db)
			console.timeEnd("parse_data");
			console.time("update_data");
			if (_data) {
				fs.writeFileSync(__dirname + "/.db/" + (fileName || "data.cache.json"), _data);
			}
			console.timeEnd("update_data");
			//clearTimeout _ti
			_ti = null;
		},
		_updateCache: function() {
			clearTimeout(_ti);
			_ti = setTimeout(foo.__updateCache, 1000);
		},
		insert: function(db_name, obj, index) {
			db_name = db_name.toLowerCase();
			var table = _db[db_name];
			if (!table) {
				table = _db[db_name] = []
					//索引
				_index[db_name] = table._ = {};
			}
			var table_index = _index[db_name]
			if (!table_index[obj._id]) { //避免update后再insert
				table.push(obj);
			}
			if (obj._id || (obj._id = index)) {
				table_index[obj._id] = obj;
			}
			foo.emit("insert", db_name, obj);
			foo._updateCache( /*缓存到JSON文件中*/ );
		},
		find_by_id: function(db_name, id) {
			db_name = db_name.toLowerCase();
			var table_index = _index[db_name];
			if (table_index) {
				return table_index[id];
			}
		},
		find_one: function(db_name, obj) {
			db_name = db_name.toLowerCase();
			var table = _db[db_name];
			var result;
			if (table instanceof Array) {
				table.every(function(item_obj) {
					if (obj_has(item_obj, obj)) {
						result = item_obj;
					} else {
						return true;
					}
				});
			}
			return result;
		},
		find_last_one: function(db_name, obj, sort_key, no_asc) {
			//默认是大~小
			db_name = db_name.toLowerCase();
			var table = _db[db_name];
			var result;
			if (table instanceof Array) {
				table = foo._sortBy(table, sort_key, !no_asc)
				for (var i = table.length - 1, item_obj; item_obj = table[i]; i -= 1) {
					if (obj_has(item_obj, obj)) {
						result = item_obj;
						break;
					}
				}
			}
			return result;
		},
		find_list: function(db_name, obj, num, page) {
			num || (num = Number.MAX_VALUE);
			page || (page = 0);
			var _start_index = (num * page) || 0;
			db_name = db_name.toLowerCase();
			var table = _db[db_name];
			var result = [];
			if (table instanceof Array) {
				for (var i = _start_index, item_obj; item_obj = table[i]; i += 1) {
					if (obj_has(item_obj, obj)) {
						result.push(item_obj)
					}
					if (result.length > num) {
						break
					}
				}
			}
			return result;
		},
		find_all: function(db_name) {
			db_name = db_name.toLowerCase();
			return _db[db_name] || [];
		},
		update: function(db_name, obj_index, obj, _is_cover) {
			db_name = db_name.toLowerCase();
			var old_obj = foo.find_by_id(db_name, obj_index);
			if (old_obj) {
				for (var key in obj) {
					if (obj.hasOwnProperty(key)) {
						old_obj[key] = obj[key];
					}
				}
				if (_is_cover) {
					for (var key in old_obj) {
						if (!obj.hasOwnProperty(key)) {
							delete old_obj[key]
						}
					}
				}
				obj._id = obj_index;
				//更新索引的对象
				_index[db_name][old_obj._id] = old_obj;
				foo._updateCache( /*缓存到JSON文件中*/ );
			} else {
				foo.insert(db_name, obj, obj_index);
			}
		},
		remove: function(db_name, obj_index) {
			db_name = db_name.toLowerCase();
			var table = _db[db_name];
			var remover;
			table.every(function(obj, index) {
				if (obj._id === obj_index) {
					remover = obj;
					table.splice(index, 1);
					return false;
				}
				return true;
			});
			if (remover) {
				_index[db_name][obj_index] = null;
				foo._updateCache( /*缓存到JSON文件中*/ );
			}
		},
		remove_list: function(db_name, obj) {
			var remover_list = foo.find_list(db_name, obj);
			remover_list.forEach(function(remover) {
				foo.remove(db_name, remover._id);
			});
		},
		remove_all: function(db_name) {
			db_name = db_name.toLowerCase();
			_db[db_name] = [];
			_index[db_name] = {};
			foo._updateCache( /*缓存到JSON文件中*/ );
		},
		fix_no_id_data: function(db_name) {
			db_name = db_name.toLowerCase();
			var table = _db[db_name];
			var new_table = [];
			table.forEach(function(item) {
				if (item._id) {
					new_table.push(item)
				}
			});
			_db[db_name] = new_table;
			foo._refreshIndex_by_dbName(db_name);
			foo._updateCache( /*缓存到JSON文件中*/ );
		},
		refreshIndex: function() {
			//重置索引，消除数组冗余
			_index = {};
			for (var dbname in _db) {
				foo._refreshIndex_by_dbName(dbname);
			}
		},
		_refreshIndex_by_dbName: function(dbname) {
			if (_db.hasOwnProperty(dbname)) {
				var table = _index[dbname] = {};
				var _arr = _db[dbname];
				if (_arr instanceof Array) {
					for (var i = 0, len = _arr.length; i < len; i += 1) {
						var obj = _arr[i];
						if (!obj) {
							continue;
						}
						var old_obj = table[obj._id];
						if (old_obj) {
							//删除冗余数据
							_arr.splice(_arr.indexOf(old_obj), 1);
							i -= 1;
						}
						table[obj._id] = obj;
					}
				}
			}
		},
		mulCall: function(method, args) {
			var method_name_map = {
				"insert": "insert",
				"findAll": "find_all",
				"findOne": "find_one",
				"findById": "find_by_id",
				"findList": "find_list",
				"update": "update",
				"remove": "remove",
			}
			var method_foo = foo[method_name_map[method]];
			return args.map(function(params) {
				return method_foo.apply(foo, params)
			});
		},
		//排序函数
		_sortBy: require("./skill").sortBy,
		_obj_has: obj_has,
		_db: _db
	};
	foo.__proto__ = EventEmitter.prototype;
	EventEmitter.call(foo);
	module.exports = foo;

	// var testArr = [{v:1},{v:3},{v:2}]
	// var res = foo._sortBy(testArr,"v",true);
	// console.log(res);

	// var me = foo.find_last_one("visitorinfo", {
	// 	bus_id: "www",
	// 	user_ip: "127.0.0.1"
	// }, "begin_visit_time");
	// console.log(me);

}());